using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Runtime.Remoting;
using System.Runtime.Serialization;

////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Dimok
//
// summary:	.
////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Dimok
{
	[Serializable]
	public class FileNotLoaded : RemotingException,ISerializable{
		private string message;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="message">	The message. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public FileNotLoaded(string message){
			this.message = message;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">			Filename of the file. </param>
		/// <param name="milliseconds">	The milliseconds. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public FileNotLoaded(string fileName,int milliseconds){
			message = "Loading of "+fileName+" took more than "+milliseconds+" milliseconds";
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">			Filename of the file. </param>
		/// <param name="milliseconds">	The milliseconds. </param>
		/// <param name="exc">					The exc. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public FileNotLoaded(string fileName,int milliseconds,Exception exc){
			message = "Loading of "+fileName+" took more than "+milliseconds+" milliseconds.\n"+exc.Message+"\n\n"+exc.StackTrace;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	Filename of the file. </param>
		/// <param name="exc">			The exc. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public FileNotLoaded(string fileName,Exception exc){
			message = fileName+"\n"+exc.Message+"\n\n"+exc.StackTrace;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="info">			The information. </param>
		/// <param name="context">	The context. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public FileNotLoaded(SerializationInfo info, StreamingContext context){
			message = (string)info.GetValue("message", typeof(string));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with the data
		/// needed to serialize the target object. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="info">			The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> to
		/// 												populate with data. </param>
		/// <param name="context">	The destination (see <see cref="T:
		/// 												System.Runtime.Serialization.StreamingContext" />) for this
		/// 												serialization. </param>
		///
		/// ### <exception cref="T:System.Security.SecurityException">	The caller does not have the
		/// 																														required permission. </exception>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public override void GetObjectData(SerializationInfo info, StreamingContext context){
			info.AddValue("message", message);
		}

		// Returns the exception information. 

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a message that describes the current exception. </summary>
		///
		/// <value>	The message. </value>
		///
		/// ### <returns>	
		/// The error message that explains the reason for the exception, or an empty string(""). 
		/// </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public override string Message{get {return message;}}

	}
	public class FileManager {

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the files. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="path">	Full pathname of the file. </param>
		///
		/// <returns>	The files. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static StringList GetFiles(string path){return GetFiles(path,"*.*");}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the files. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="path">			Full pathname of the file. </param>
		/// <param name="pattern">	(*) </param>
		///
		/// <returns>	The files. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static StringList GetFiles(string path,string pattern){
			StringList slFiles = new StringList();
			foreach( string fileName in Directory.GetFiles(path,pattern) )
				slFiles.Add(fileName);
			foreach( string dirName in Directory.GetDirectories(path) )
				slFiles.AddRange(GetFiles(dirName,pattern));
			return slFiles;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get list of files - path\filename(ver).ext. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	The file versions. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static StringList GetFileVersions(string fileName){
			return GetFileVersions(fileName,"(*)");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get list of files - path\filename(ver).ext. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="pattern">	(*) </param>
		///
		/// <returns>	The file versions. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static StringList GetFileVersions(string fileName,string pattern){
			StringList files = new StringList(Directory.GetFiles(Path.GetDirectoryName(fileName),Path.GetFileNameWithoutExtension(fileName)+pattern+Path.GetExtension(fileName)));
			return files;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get last file name from path\filename(ver).ext. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="pattern">	(*) </param>
		///
		/// <returns>	The last version. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetLastVersion(string fileName,string pattern){
			StringList files = GetFileVersions(fileName,pattern);
			return files.Count > 0 ? files[files.Count-1] : "";
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Shift file's version: fileName(02).ext -> fileName(03).ext. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="pattern">	"(0000)". </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void ShiftVersions(string fileName,string pattern){
			string filter = pattern[0] + Regex.Replace(pattern.Substring(1,pattern.Length-2),".","?") + pattern[pattern.Length-1];
			string[] files = GetFileVersions(fileName,filter);
			Array.Reverse(files);
			foreach( string file in files ){
				int version = int.Parse(GetFileVersion(file,pattern));
				File.Move(file,BuildFileVersion(fileName,version+1,pattern));
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a file version. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="template">	The template. </param>
		///
		/// <returns>	The file version. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetFileVersion(string fileName,string template){
			string start = Regex.Escape(template[0]+"");
			string end = Regex.Escape(template[template.Length-1]+"");
			return Regex.Match(fileName,start+@"(?<ver>\d+)"+end+"[.]...$",RegexOptions.IgnoreCase).Groups["ver"].Value;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Builds a file version. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="version">	The version. </param>
		/// <param name="format">		"00000" - default. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string BuildFileVersion(string fileName,int version,string format){
			string start = "(";
			string end = ")";
			if( Regex.IsMatch(format,"^\\D") ){
				start = format[0]+"";
				end = format[format.Length-1]+"";
				format = format.Substring(1,format.Length-2);
			}
			return Path.GetDirectoryName(fileName)+"\\"+Path.GetFileNameWithoutExtension(fileName) + start+(version).ToString(format)+end+Path.GetExtension(fileName);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Merges the given file. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileNameTo">			The file name to. </param>
		/// <param name="fileNameFrom">		The file name from. </param>
		/// <param name="deleteFileFrom">	true to delete the file from. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void Merge(string fileNameTo,string fileNameFrom,bool deleteFileFrom){
			StreamWriter sw = File.Exists(fileNameTo) ? File.AppendText(fileNameTo) : File.CreateText(fileNameTo);
			StreamReader sr = File.OpenText(fileNameFrom);
			sw.Write(sr.ReadToEnd());
			sr.Close();
			sw.Flush();
			sw.Close();
			if( deleteFileFrom )File.Delete(fileNameFrom);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first files. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="path">			Full pathname of the file. </param>
		/// <param name="filters">	A variable-length parameters list containing filters. </param>
		///
		/// <returns>	The found files. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string[] FindFiles(string path,params string[] filters){
			StringCollection list = new StringCollection();
			foreach( string filter in filters )
				list.AddRange(Directory.GetFiles(path,filter));
			return (string[])new ArrayList(list).ToArray(typeof(string));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Clean folder. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="path">	Full pathname of the file. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void CleanFolder(string path){
			foreach( string fileName in Directory.GetFiles(path) )
				File.Delete(fileName);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Converts fileIn into byte[]. If deleteFileIn is set to true fileIn will be deleted from disk. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileIn">	The file in. </param>
		///
		/// <returns>	The bytes from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetBytesFromFile(string fileIn) {
			return GetBytesFromFile(fileIn,false);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Converts fileIn into byte[]. If deleteFileIn is set to true fileIn will be deleted from disk. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileNames">	List of names of the files. </param>
		///
		/// <returns>	The bytes from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] GetBytesFromFile(string[] fileNames){
			return GetBytesFromFile(fileNames,false);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Converts fileIn into byte[]. If deleteFileIn is set to true fileIn will be deleted from disk. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileNames">		List of names of the files. </param>
		/// <param name="deleteFiles">	true to delete the files. </param>
		///
		/// <returns>	The bytes from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] GetBytesFromFile(string[] fileNames,bool deleteFiles){
			return GetBytesFromFile(fileNames,deleteFiles,false);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Converts fileIn into byte[]. If deleteFileIn is set to true fileIn will be deleted from disk. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="folderName">		Pathname of the folder. </param>
		/// <param name="deleteFiles">	true to delete the files. </param>
		/// <param name="deleteFolder">	Pathname of the delete folder. </param>
		///
		/// <returns>	The bytes from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] GetBytesFromFile(string folderName,bool deleteFiles,bool deleteFolder){
			return GetBytesFromFile(Directory.GetFiles(folderName),deleteFiles,deleteFolder);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Converts fileIn into byte[]. If deleteFileIn is set to true fileIn will be deleted from disk. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileNames">		List of names of the files. </param>
		/// <param name="deleteFiles">	true to delete the files. </param>
		/// <param name="deleteFolder">	Pathname of the delete folder. </param>
		///
		/// <returns>	The bytes from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] GetBytesFromFile(string[] fileNames,bool deleteFiles,bool deleteFolder){
			ArrayListEx alFiles = new ArrayListEx();
			foreach( string fileName in fileNames )
				alFiles.Add(GetBytesFromFile(fileName,deleteFiles));
			if( deleteFiles && deleteFolder && fileNames.Length > 0 )
				Directory.Delete(Path.GetDirectoryName(fileNames[0]),true);
			return alFiles;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Converts fileIn into byte[]. If deleteFileIn is set to true fileIn will be deleted from disk. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <exception cref="FileNotFoundException">	Thrown when the requested file is not present. </exception>
		///
		/// <param name="fileName">			Filename of the file. </param>
		/// <param name="deleteFileIn">	true to delete the file in. </param>
		///
		/// <returns>	The bytes from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetBytesFromFile(string fileName,bool deleteFileIn) {
			if(!File.Exists(fileName)) throw new FileNotFoundException("File "+fileName+" cannot be not found.",fileName);
			try{
				using(FileStream fs = File.OpenRead(fileName)){
					byte[] bt = new byte[fs.Length]; 
					fs.Read(bt,0,(int)fs.Length);
					return bt;
				}
			}finally{
				if(deleteFileIn) File.Delete(fileName);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a text from file. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	The text from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetTextFromFile(string fileName){return GetTextFromFile(fileName,false);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a text from file. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <exception cref="FileNotFoundException">	Thrown when the requested file is not present. </exception>
		///
		/// <param name="fileName">			. </param>
		/// <param name="deleteFileIn">	true to delete the file in. </param>
		///
		/// <returns>	The text from file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetTextFromFile(string fileName,bool deleteFileIn) {
			if(!File.Exists(fileName)) throw new FileNotFoundException("File "+fileName+" cannot be not found.",fileName);
			try{
				using(StreamReader fs = File.OpenText(fileName)){
					return fs.ReadToEnd();
				}
			}finally{
				if(deleteFileIn) File.Delete(fileName);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Creates file on disk from fileIn with temporary file name and returns it. You have to know the
		/// type of fileIn (pdf, tif, etc.) and pass it correct fileExtension. 
		/// </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileIn">	The file in. </param>
		///
		/// <returns>	The file from bytes. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetFileFromBytes(byte[] fileIn){
			return GetFileFromBytes(fileIn,"");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Creates file on disk from fileIn with fileName. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileIn">		. </param>
		/// <param name="fileName">	Can be partial(".tif",Some.pdf","X:\Path\","") </param>
		///
		/// <returns>	The file from bytes. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetFileFromBytes(byte[] fileIn,string fileName){
			return GetFileFromBytes(fileIn,fileName,true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Create file from byte array. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileIn">			byte array. </param>
		/// <param name="fileName">		Name of out file (BuildFullFileName is used as a filter) </param>
		/// <param name="createNew">	If CreateNew == true (default) - create a unique name if [fileName]
		/// 													already exists. </param>
		///
		/// <returns>	Name of created file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetFileFromBytes(byte[] fileIn,string fileName,bool createNew){
			try{
				fileName = BuildFullFileName(fileName,createNew);
				FileStream fs = null;
				try{
					fs = File.Create(fileName);
				}catch(Exception){
					fileName = GetSureFileName(fileName);
					fs = File.Create(fileName);
				}
				if( fileIn != null )fs.Write(fileIn,0,fileIn.Length);
				fs.Close();
				return fileName;
			}catch(Exception exc){ throw new Exception("File Name:"+fileName,exc); }
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Create file from text. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="text">				text. </param>
		/// <param name="fileName">		Name of out file (BuildFullFileName is used as a filter) </param>
		/// <param name="createNew">	If CreateNew == true (default) - create a unique name if [fileName]
		/// 													already exists. </param>
		///
		/// <returns>	Name of created file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetFileFromBytes(string text,string fileName,bool createNew){
			fileName = BuildFullFileName(fileName,createNew);
			StreamWriter sw = File.CreateText(fileName);
			if( text != null && text != "" )sw.Write(text);
			sw.Close();
			return fileName;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Wait to load. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <exception cref="FileNotLoaded">	Thrown when file not loaded. </exception>
		///
		/// <param name="fileName">			. </param>
		/// <param name="milliseconds">	The milliseconds. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void WaitToLoad(string fileName,int milliseconds) {
			if( Directory.Exists(fileName) )return;
			DateTime dtStart = DateTime.Now;
			TimeSpan ts = new TimeSpan(0);
			while(true){
				try {
					ts = DateTime.Now.Subtract(dtStart);
					FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
					fs.Close();
					return;
				}
				catch(FileNotFoundException exc) {
					throw new FileNotLoaded(fileName,exc);
				}
				catch(Exception exc) {
					if(ts.TotalMilliseconds > milliseconds)
						throw new FileNotLoaded(fileName,milliseconds,exc);
					Thread.Sleep(1000);
					continue;
				}
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Change file extension. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">					. </param>
		/// <param name="extensionWithDot">	The extension with dot. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string ChangeFileExtension(string fileName,string extensionWithDot) {
			string newName = Path.Combine(Path.GetDirectoryName(fileName),Path.GetFileNameWithoutExtension(fileName)+extensionWithDot);
			File.Move(fileName,newName);
			return newName;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a new file name. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fullName">	Name of the full. </param>
		/// <param name="newName">	Name of the new. </param>
		///
		/// <returns>	The new file name. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetNewFileName(string fullName,string newName){
			if( newName.IndexOf("+") == 0 )newName = Path.GetFileNameWithoutExtension(fullName)+newName.Substring(1);
			return Path.Combine(Path.GetDirectoryName(fullName),Path.Combine(newName,Path.GetExtension(fullName)));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a sure path. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="path">	Full pathname of the file. </param>
		///
		/// <returns>	The sure path. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetSurePath(string path) {
			string pathNew = path;
			for( int i=0; Directory.Exists(pathNew); i++ )
				pathNew = path + "("+(i+1).ToString("000")+")";
			return pathNew;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Build unique file name in file's directory by adding (xxx) to file's name. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="filePath">	Full file name. </param>
		///
		/// <returns>	Unique file name. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetSureFileName(string filePath){return GetSureFileName(filePath,"00000");}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Build unique file name in file's directory by adding (xxx) to file's name. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="filePath">	Full file name. </param>
		/// <param name="format">		"00000" - default. </param>
		///
		/// <returns>	Unique file name. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetSureFileName(string filePath,string format){
			string pathNew = filePath;
			for( int i=0; File.Exists(pathNew); i++ )
				pathNew = BuildFileVersion(filePath,i+1,format);
			return pathNew;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Add missing paths in file name. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">		Could be: path\name.ext or name.ext or .ext if no name provided -
		/// 													temp name will be added , if no path provided - temp path will be
		/// 													added , if no path provided and createNew=true - temp will be added
		/// 													to name part. </param>
		/// <param name="createNew">	Add (nnn) to file name if file with such name exists. </param>
		///
		/// <returns>	Fully structured file name - PATH\NAME.EXT. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string BuildFullFileName(string fileName,bool createNew){
			return BuildFullFileName(fileName,"tmp",createNew);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Add missing paths in file name. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">					Could be: path\name.ext or name.ext or .ext if no name provided
		/// 																- temp name will be added , if no path provided - temp path
		/// 																will be added , if no path provided and createNew=true - temp
		/// 																will be added to name part. </param>
		/// <param name="defaultExtension">	Default extension, if not provided. </param>
		/// <param name="createNew">				Add (nnn) to file name if file with such name exists. </param>
		///
		/// <returns>	Fully structured file name - PATH\NAME.EXT. </returns>
		///
		/// <example>	
		/// Examle:
		/// <code>
		/// if no name provided - temp name will be added
		/// if no path provided - temp path will be added
		/// if no path provided and createNew=true - temp will be added to name part
		/// </code>
		/// </example>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string BuildFullFileName(string fileName,string defaultExtension,bool createNew){
			if( fileName == null )fileName = "";
			if( fileName == "" || Path.GetDirectoryName(fileName) == string.Empty ){
				if( createNew )fileName = GetTempFileName(fileName);
				fileName = Path.Combine(Path.GetTempPath(),fileName);
			}
			if( Path.GetFileNameWithoutExtension(fileName) == string.Empty )
				fileName = GetTempFileName(fileName);
			if( Path.GetExtension(fileName) == string.Empty )
				fileName = Path.ChangeExtension( fileName,defaultExtension);
			return createNew ? GetSureFileName(fileName) : fileName;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a temp file name. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	The temp file name. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetTempFileName(string fileName){
			string temp = "~Temp"+DateTime.Now.Ticks.ToString("X");
			return fileName == "" ? temp : Regex.Replace(fileName,"([.].+?)$",temp+"$&",RegexOptions.RightToLeft);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the files described by path. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="path">	Full pathname of the file. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeleteFiles(string path){DeleteFiles(Directory.GetFiles(path));}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the files described by path. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="fileNames">	List of names of the files. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeleteFiles(ArrayList fileNames){DeleteFiles((string[])fileNames.ToArray(typeof(string)));}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the files described by path. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileNames">	List of names of the files. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void DeleteFiles(string[] fileNames){
			foreach( string fileName in fileNames )
				try{
					File.Delete(fileName);
				}catch(Exception exc){
					throw new Exception("FileName:"+fileName+Environment.NewLine,exc);
				}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Queries if a given file exists. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="filePattern">	The file pattern. </param>
		///
		/// <returns>	true if it succeeds, false if it fails. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static bool FileExists(string filePattern){
			foreach( string fileName in Directory.GetFiles(filePattern) )
				if( File.Exists(fileName) )return true;
			return false;
		}
		#region PageNumbers
			#region MakePageNumbers

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Makes a page numbers inverted. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="pageCount">		. </param>
		/// <param name="pageNumbers">	1 - based. </param>
		///
		/// <returns>	A list of. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static ArrayListEx MakePageNumbersInverted(int pageCount, int[] pageNumbers) {
			List<int> lstPages = new List<int>((int[])MakePageNumbers(pageCount,pageNumbers));
			ArrayListEx alOut = new ArrayListEx();
			foreach (int page in MakePageNumbers(pageCount, null))
				if( !lstPages.Contains(page) )alOut.Add(page);
			return alOut;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Make array of page numbers out of int[]. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="pageCount">		. </param>
		/// <param name="pageNumbers">	1 - based. </param>
		///
		/// <returns>	A list of. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static ArrayListEx MakePageNumbers(int pageCount,int[] pageNumbers){
			if( IsAllPages(pageNumbers) )return MakePageNumbers(1,pageCount);
			if( pageNumbers.Length == 1 && pageNumbers[0] < 0 )return MakePageNumbers(-pageNumbers[0],pageCount);
			return new ArrayListEx(pageNumbers);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Make array of page numbers out of int[]. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="start">	The start. </param>
		/// <param name="stop">		The stop. </param>
		///
		/// <returns>	A list of. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static ArrayListEx MakePageNumbers(int start, int stop){
			ArrayListEx alx = new ArrayListEx();
			for( int p = start; p <= stop; p++ )
				alx.Add(p);
			return alx;
		}
			#endregion MakePageNumbers

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Query if 'pages' is all pages. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="pages">	The pages. </param>
		///
		/// <returns>	true if all pages, false if not. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static bool IsAllPages(string pages){
			return IsAllPages((int[])new StringList(pages));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Query if 'pages' is all pages. </summary>
		///
		/// <remarks>	Dimon, 11/23/2010. </remarks>
		///
		/// <param name="pageNumbers">	1 - based. </param>
		///
		/// <returns>	true if all pages, false if not. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static bool IsAllPages(params int[] pageNumbers){
			return pageNumbers == null || pageNumbers.Length == 0 || pageNumbers.Length == 1 && pageNumbers[0] == -1;
		}
		#endregion
	}
}